package org.example.config;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.example.compent.DynamicDatasource;
import org.example.util.DynamicDatasourceContextHolder;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Donald
 * @create 2020-04-18 22:46
 */
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
@MapperScan(basePackages = {"org.example.**.mapper"})
public class DynamicDatasourceConfig {

    private Map<String,String> master;

    private Map<String,String> salv;

    private Map<String,String> oral;

    public void setMaster(Map<String, String> master) {
        this.master = master;
    }

    public void setSalv(Map<String, String> salv) {
        this.salv = salv;
    }

    public void setOral(Map<String, String> oral) {
        this.oral = oral;
    }

    /**
     * 不通过druid pool 创建链接
     * @return
     * @throws Exception
     */
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource getDataSource(){
        return DataSourceBuilder.create().build();
    }
    @Bean("master")
    public DataSource master() throws Exception{
        DataSource dataSource = DruidDataSourceFactory.createDataSource(master);
        return dataSource;
    }

    @Bean("slave")
    public DataSource slave() throws Exception{
        DataSource dataSource = DruidDataSourceFactory.createDataSource(salv);
        return dataSource;
    }

    @Bean("oracle")
    public DataSource orcal() throws Exception{
        DataSource dataSource = DruidDataSourceFactory.createDataSource(oral);
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dynamicDatasource ) {
        // 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可
        return new DataSourceTransactionManager(dynamicDatasource);
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean( @Qualifier("dynamicDataSource") DataSource dynamicDatasource )  throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource作为数据源则不能实现切换
        sessionFactory.setDataSource(dynamicDatasource);
        sessionFactory.setTypeAliasesPackage("org.example.**.entity");    // 扫描entity
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setMapperLocations(resolver.getResources("classpath*:**/mapper/*Mapper.xml"));    // 扫描映射文件
        return sessionFactory;
    }

    @Bean("dynamicDataSource")
    public DataSource dynamicDataSource(@Qualifier("master") DataSource master, @Qualifier("slave")DataSource sal, @Qualifier("oracle") DataSource oracle) {
        DynamicDatasource dynamicDataSource = DynamicDatasource.getInstance();
        Map<Object, Object> dataSourceMap = new HashMap<>(3);
        dataSourceMap.put("master", master);
        dataSourceMap.put("salve", sal);
        dataSourceMap.put("oracle",oracle);
        // 将 master 数据源作为默认指定的数据源
        dynamicDataSource.setDefaultDatasource(master);
        // 将 master 和 slave 数据源作为指定的数据源
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        DynamicDatasourceContextHolder.addDataSourceKeys(Arrays.asList("master","salve","oracle"));
        return dynamicDataSource;
    }



}
